﻿//-----------------------------------------------------------------------
// <copyright file="ConsoleHosterViewModel.cs" author="Artak Mkrtchyan">
//     Creative Commons - GNU General Public License (http://creativecommons.org/licenses/GPL/2.0/
// </copyright>
// <author>Artak Mkrtchyan</author>
// <email>mkArtak@gmail.com</email>
// <date>08/12/2012</date>
//-----------------------------------------------------------------------
using AppUpdate.Common;
using ConsoleHoster.Model;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace ConsoleHoster.ViewModel
{
	public delegate void SoftwareUpdateInfoEventHandler(ConsoleHostViewModel argSender, bool argUpdateAvailable);

	public sealed partial class ConsoleHostViewModel
	{
		private string assemblyVersion;
		private readonly IUpdateManager updateManager;
		private InstallerPackageDetails availableUpdateDetails;
		private bool checkingForUpdates = false;

		public Task CheckForUpdates()
		{
			return this.CheckForUpdatesAsync(false);
		}

		private Task CheckForUpdatesAsync(bool argIsSilentUpdate)
		{
			Task tmpResult = null;

			if (!this.CheckingForUpdates && this.UpdateManager != null && !this.IsInDesignMode)
			{
				tmpResult = Task.Factory.StartNew(() =>
				{
					this.CheckingForUpdates = true;
					InstallerPackageDetails tmpNewVersion = null;
					try
					{
						tmpNewVersion = this.UpdateManager.CheckUpdateAvailability(new VersionInfo(this.CurrentAssemblyVersion));
						if (tmpNewVersion != null)
						{
							this.AvailableUpdateDetails = tmpNewVersion;

							Uri tmpIconUri = new Uri("pack://application:,,,/ConsoleHoster;component/Resources/Application.ico", UriKind.RelativeOrAbsolute);
							if (this.userInteractionManager.ConfirmWithDetails(
								String.Format("A new of the app is available (Ver.: {0}). Do you want to visit the update website to download it now?", this.AvailableUpdateDetails.Version.Version),
								"Update available",
								this.GetUpdateVersionInfo(),
								"Version info...",
								() => BitmapFrame.Create(tmpIconUri)))
							{
								this.Update();
							}
						}
						else if (!argIsSilentUpdate)
						{
							this.userInteractionManager.ShowMessage("No new version available");
						}
					}
					catch (Exception ex)
					{
						this.Logger.LogError("Error while checking for updates. Details: {0}", ex.ToString());
					}

					this.CheckingForUpdates = false;
				});
			}

			return tmpResult;
		}

		private string GetUpdateVersionInfo()
		{
			string tmpVersionDetails = null;

			VersionInfoV2 tmpVersion = this.AvailableUpdateDetails.Version as VersionInfoV2;
			if (tmpVersion != null)
			{
				tmpVersionDetails = tmpVersion.Info;
			}
			return tmpVersionDetails;
		}

		private void Update()
		{
			if (this.AvailableUpdateDetails != null && !String.IsNullOrWhiteSpace(this.AvailableUpdateDetails.DownloadUri))
			{
				this.RunActionWithErrorHandling(() =>
				{
					/// TODO: replace the following line with the two commented after, when the auto-updater logic will be tested and finalized
					this.processManager.StartProcess(this.AvailableUpdateDetails.DownloadUri);

					//string tmpLocation = await this.UpdateManager.DownloadInstallerPackageAsync(this.AvailableUpdateDetails);
					//this.UpdateManager.BeginUpdate(tmpLocation);
				}, "Failed to start the browser");
			}
		}

		public bool CheckingForUpdates
		{
			get
			{
				return this.checkingForUpdates;
			}
			private set
			{
				this.checkingForUpdates = value;
			}
		}

		public InstallerPackageDetails AvailableUpdateDetails
		{
			get
			{
				return this.availableUpdateDetails;
			}
			set
			{
				if (value != this.availableUpdateDetails)
				{
					this.availableUpdateDetails = value;
					this.NotifyPropertyChange("AvailableUpdateDetails");
				}
			}
		}

		public IUpdateManager UpdateManager
		{
			get
			{
				return this.updateManager;
			}
		}

		public bool AutoUpdateEnabled
		{
			get
			{
				return true;
			}
		}

		public string CurrentAssemblyVersion
		{
			get
			{
				if (this.assemblyVersion == null)
				{
					object[] tmpVersionAttributes = Assembly.GetCallingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
					if (!tmpVersionAttributes.Any())
					{
						throw new ApplicationException("Unable to determine assembly version");
					}
					this.assemblyVersion = tmpVersionAttributes.OfType<AssemblyFileVersionAttribute>().First().Version;
				}

				return this.assemblyVersion;
			}
		}
	}
}
